/**
 * 抖音电商罗盘工具(达人版)
 */
import { StyleProvider } from "@ant-design/cssinjs"
import { DownloadOutlined } from "@ant-design/icons"
import { BatchInterceptor } from "@mswjs/interceptors"
import { ClientRequestInterceptor } from "@mswjs/interceptors/ClientRequest"
import { FetchInterceptor } from "@mswjs/interceptors/fetch"
import { XMLHttpRequestInterceptor } from "@mswjs/interceptors/XMLHttpRequest"
import { Button, Flex, List, Modal } from "antd"
import cssText from "data-text:~/assets/css/dyCompassTalent.css"
import antdResetCssText from "data-text:antd/dist/reset.css"
import { time } from "html2canvas/dist/types/css/types/time"
import ky from "ky"
import moment from "moment"
import type {
  PlasmoCSConfig,
  PlasmoGetInlineAnchor,
  PlasmoGetShadowHostId
} from "plasmo"
import React, { useEffect, useRef, useState } from "react"
import * as XLSX from "xlsx"

import { sendToBackground } from "@plasmohq/messaging"
import { usePort } from "@plasmohq/messaging/hook"
import { useStorage } from "@plasmohq/storage/dist/hook"

import { ThemeProvider } from "~theme"
import { _callApi } from "~utils/tools"

// 注入配置
export const config: PlasmoCSConfig = {
  matches: [
    // 抖音电商罗盘(达人版-商品页)
    "https://compass.jinritemai.com/talent/product-analysis*"
  ],
  run_at: "document_start",
  all_frames: true
}

// 注入的shadow dom的id
export const HOST_ID = "dy-compass-talent-tool"
export const getShadowHostId: PlasmoGetShadowHostId = () => HOST_ID

// 注入的位置配置
export const getInlineAnchor: PlasmoGetInlineAnchor = async () => {
  // const elementList = document.querySelectorAll("div#root  div[class^='u_gwz']")
  return {
    element: document.querySelector(
      "div#root  div[class^='u_gwz'] > button:last-child"
    ),
    insertPosition: "afterend"
  }
}

// 注入样式
export const getStyle = () => {
  const style = document.createElement("style")
  style.textContent = cssText + antdResetCssText
  return style
}

// 信息通知模组
const DyCompassMessageModal: React.FC<{
  show: boolean
  handleClose: Function
  handleExport: Function
  disBtn: boolean
  btnLoading: boolean
  messages: string[]
}> = (props) => {
  // 关闭模态框回调函数
  const handleCancel = () => {
    props.handleClose()
  }
  // 处理导出事件
  const handelExportEvent = () => {
    props.handleExport()
  }

  // 消息容器引用，用于滚动到底部显示最新消息
  const messageContainerRef = useRef(null)

  // 监听 props.messages 的变化
  useEffect(() => {
    if (messageContainerRef.current) {
      // 滚动到底部
      messageContainerRef.current.scrollTop =
        messageContainerRef.current.scrollHeight
    }
  }, [props.messages]) // 当 props.messages 变化时触发

  return (
    <ThemeProvider>
      <StyleProvider container={document.getElementById(HOST_ID).shadowRoot}>
        <Modal
          width={720}
          title={"明细数据下载中..."}
          className={"data-modal-wrapper"}
          footer={null}
          mask={true}
          keyboard={false}
          maskClosable={false}
          closable={!props.disBtn}
          open={props.show}
          onCancel={handleCancel}
          onOk={handleCancel}
          getContainer={false}>
          <div className={"data-message-box-wrap"} ref={messageContainerRef}>
            {props.messages.map((message, index) => (
              <div className={"message-item"} key={index}>
                {message}
              </div>
            ))}
          </div>
          <div className={"data-export-btn-wrap"}>
            <Button
              size={"small"}
              disabled={props.disBtn}
              onClick={handelExportEvent}
              loading={props.btnLoading}>
              导出数据
            </Button>
          </div>
        </Modal>
      </StyleProvider>
    </ThemeProvider>
  )
}

//
const DyCompassTool: React.FC = () => {
  // 通知模组显示状态
  const [showMessageBox, setShowMessageBox] = useState(false)
  // 通知模组消息列表
  const [messageList, setMessageList] = useState<string[]>([])
  // 验证参数记录
  const [requestParams, setRequestParams] = useState({})
  // 店铺信息缓存
  const [shopInfoCache, setShopInfoCache] = useState({})
  // 导出按钮禁用状态
  const [disExportBtn, setDisExportBtn] = useState(true)
  // 导出数据状态
  const [exporting, setExporting] = useState(false)
  // 用户是否登录
  const [userLogin] = useStorage("isLogin", false)

  // 后端请求拦截信息响应
  const requestEventHandler = (message: {
    action: string
    data: { url: string; params: any }
  }) => {
    /**
     * 从background中，拦截请求，并提取必要的参数，保存到组件状态中以供后续使用
     */
    if (message.action === "webRequest") {
      // 从message.data.params中提取所需的必要参数
      const paramsKeys = [
        "fp", // 接口请求验证参数
        "msToken", // 用户身份验证token
        "verifyFp", // 额外验证参数
        "begin_date", // 数据开始时间
        "end_date", // 数据结束时间
        "date_type", // 时间类型
        "_lid" // 日志id
      ]

      // 使用reduce来提取参数
      const extractedParams = paramsKeys.reduce((acc: any, key: string) => {
        if (key in message.data.params) {
          acc[key] = message.data.params[key]
        }
        return acc
      }, {})
      // 检查所有参数是否齐全
      const allKeysPresent = paramsKeys.every((key) => {
        return extractedParams.hasOwnProperty(key)
      })

      if (allKeysPresent) {
        // 所有参数齐全，保存到组件状态中以供后续使用
        setRequestParams(extractedParams)
      }
    }
  }

  // 处理显示通知模组
  const handleShowMessageBox = () => {
    setShowMessageBox(true)
  }

  // 处理关闭通知模组
  const handleCloseMessageBox = () => {
    setShowMessageBox(false)
  }

  // 获取查询开始日期
  const getBeginDate = (format: string = "YYYY-MM-DD") => {
    try {
      return moment(requestParams["begin_date"]).format(format)
    } catch (e) {
      return "未知开始日期"
    }
  }
  // 获取查询结束日期
  const getEndDate = (format: string = "YYYY-MM-DD") => {
    try {
      return moment(requestParams["end_date"]).format(format)
    } catch (e) {
      return "未知结束日期"
    }
  }

  // 处理消息列表更新
  const updateMessageList = (msg: string, init: boolean = false) => {
    if (init) {
      // 清空列表
      setMessageList([])
    } else {
      // 添加信息
      messageList.push(msg)
      setMessageList([...messageList]) // 更新状态以触发重新渲染
    }
  }

  // 添加店铺信息到缓存，店铺信息为对象，包含店铺名称和商品信息
  const addShopInfoToCache = (shopInfo: any) => {
    // 根据requestParams中的begin_date和end_date作为key
    const _key = `${requestParams["begin_date"]}_${requestParams["end_date"]}`
    setShopInfoCache((prevShopInfo) => ({
      ...prevShopInfo,
      [_key]: shopInfo
    }))
  }
  // 从缓存中获取店铺信息, 无缓存返回undefined
  const getShopInfoFromCache = () => {
    // 根据requestParams中的begin_date和end_date作为key
    const _key = `${requestParams["begin_date"]}_${requestParams["end_date"]}`
    return shopInfoCache[_key]
  }

  // 请求处理
  useEffect(() => {
    // 监听background数据
    chrome.runtime.onMessage.addListener(requestEventHandler)

    // 卸载background监听
    return () => {
      chrome.runtime.onMessage.removeListener(requestEventHandler)
    }
  }, [])

  // 获取完整的url请求链接
  const getCompleteUrl = async (baseUrl: string, params: any) => {
    /**
     * @description 用于生成完整的请求URL，增加加密验证参数
     * @param {string} baseUrl - 基础URL地址
     * @param {Object} params - 请求参数对象
     * @returns {string} - 完整的URL字符串
     */
    // 加入验证用的额外参数，从requestParams中获取
    const _tempParams = {
      ...params,
      msToken: requestParams["msToken"],
      verifyFp: requestParams["verifyFp"],
      fp: requestParams["fp"],
      _lid: requestParams["_lid"]
    }
    const queryString = new URLSearchParams(_tempParams).toString()
    const _tempUrl = `${baseUrl}?${queryString}`
    // 获取user_agent
    const userAgent = navigator.userAgent
    // 获取a_bogus加密参数
    // 请求验证参数
    const { data: paramsRes } = await _callApi("getDyRequestParam", {
      url: _tempUrl,
      data: "",
      user_agent: userAgent
    })
    if (paramsRes["success"]) {
      return paramsRes["url"]
    } else {
      return _tempUrl
    }
  }

  // 获取合作商家列表
  const handleGetShopList = async (
    page_no: number = 1,
    page_size: number = 100
  ) => {
    const _baseUrl =
      "https://compass.jinritemai.com/compass_api/author/cooperative_shop_review/shop_list"
    const _params = {
      is_asc: false,
      page_no: page_no,
      page_size: page_size,
      selected_index: "pay_amt,pay_ucnt,real_refund_amt",
      activity_id: "",
      begin_date: requestParams["begin_date"],
      end_date: requestParams["end_date"],
      date_type: requestParams["date_type"]
    }

    // 获取完整的请求url
    const requestUrl = await getCompleteUrl(_baseUrl, _params)
    // 使用Ky进行Get请求
    const response = await ky.get(requestUrl)
    const data = (await response.json()) as any
    /**
     * 返回的数据结构：{
     *     data:{
     *         head:[],
     *         page_result:{
     *             page_no: number,
     *             page_size: number,
     *             total: number
     *         },
     *         rows:[
     *             {
     *                 cells:[
     *                     {
     *                         shop_item:{
     *                             name:"",
     *                             id:"",
     *                         }
     *                     }
     *                 ]
     *             }
     *         ]
     *     }
     * }
     */
    // 来自数据的page_result中的总数
    const total = data?.data?.page_result?.total || 0
    // 解构data中的shop_item生成shop_list
    const shop_list_data = data?.data?.rows || []
    const shop_list = shop_list_data.map((item: any) => {
      const shop_item = item.cells[0].shop_item
      return {
        id: shop_item.id,
        name: shop_item.name
      }
    })
    return { shop_list, total }
  }

  // 获取商家商品列表
  const handleGetProductList = async (
    shopId: number,
    page_no: number = 1,
    page_size: number = 1000
  ) => {
    const _baseUrl =
      "https://compass.jinritemai.com/compass_api/author/cooperative_shop_review/shop_product_list"
    const _params = {
      begin_date: requestParams["begin_date"],
      end_date: requestParams["end_date"],
      date_type: requestParams["date_type"],
      activity_id: "",
      page_no: page_no,
      shop_id: shopId,
      page_size: page_size
    }
    // 获取完整的请求url
    const requestUrl = await getCompleteUrl(_baseUrl, _params)
    // 使用Ky进行Get请求
    const response = await ky.get(requestUrl)
    const data = (await response.json()) as any
    /**
     * 返回的数据结构:{
     *      data:{
     *               head:[],
     *      page_result:{
     *          page_no:number,
     *          page_size:number,
     *          total:number
     *      },
     *      rows:[
     *          {
     *              cells:[
     *                  {data_type:string,value_str:string},
     *                  {
     *                      product_item:{
     *                          id: "商品编码",
     *                          title: "商品名称"
     *                      }
     *                  }
     *              ]
     *          }
     *      ]
     *      }
     * }
     */
    // 来自数据的page_result中的总数
    const total = data?.data?.page_result?.total || 0
    // 解构商品列表
    const product_list_data = data?.data?.rows || []
    const product_list = product_list_data.map((item: any) => {
      const product_item = item.cells[1].product_item
      return {
        id: product_item.id,
        title: product_item.title
      }
    })
    return { product_list, total }
  }

  // 下载明细列表
  const handleDownloadDetail = async () => {
    setExporting(true)
    setDisExportBtn(true)
    try {
      const _baseUrl =
        "https://compass.jinritemai.com/compass_api/author/product/product_analysis/product_list/download"
      const _params = {
        begin_date: requestParams["begin_date"],
        end_date: requestParams["end_date"],
        date_type: requestParams["date_type"],
        activity_id: "",
        selected_index:
          "pay_amt,pay_ucnt,real_refund_amt,estimate_commission,author_real_commission"
      }
      // 获取完整的请求url
      const requestUrl = await getCompleteUrl(_baseUrl, _params)
      // 使用Ky进行Get请求
      const response = await ky.get(requestUrl)
      // 响应中处理Excel下载
      let blob = await response.blob()
      // 编辑excel文件
      const arrayBuffer = await blob.arrayBuffer()
      const data = XLSX.read(arrayBuffer, { type: "array" })
      const worksheet = data.Sheets["商品分析"]
      const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 })

      // 添加序号列到标题行
      if (jsonData.length > 0) {
        // header增加
        jsonData[0] = ["商户ID", "商户名称", ...(jsonData[0] as [])]

        if (jsonData.length > 1) {
          // 构建商户信息索引，以商品编号为Key
          const shopInfoMap = {}
          // 从商户信息缓存中构建
          const _tempShopInfoCache = getShopInfoFromCache()
          // 循环shopInfoCache
          for (let key in _tempShopInfoCache) {
            const shopName = _tempShopInfoCache[key]["name"]
            // 循环商户商品列表
            _tempShopInfoCache[key]["products"].forEach((p) => {
              shopInfoMap[Number(p.id)] = {
                shopId: key,
                shopName: shopName
              }
            })
          }

          // 完善数据，添加商品对应的商户信息
          for (let i = 1; i < jsonData.length; i++) {
            // 商品id
            const pid = Number(jsonData[i][2])
            // 店铺id
            const sid = shopInfoMap[pid]?.shopId || ""
            // 店铺名称
            const sName = shopInfoMap[pid]?.shopName || ""
            jsonData[i] = [sid, sName, ...(jsonData[i] as [])]
          }
        }
      }
      // 将修改后的数据转换为新的Worksheet
      const newWorksheet = XLSX.utils.json_to_sheet(jsonData, {
        skipHeader: true
      })
      const newWorkbook = XLSX.utils.book_new()
      // 写入sheet
      XLSX.utils.book_append_sheet(newWorkbook, newWorksheet, "商品分析")

      // 下载xlsx文件
      XLSX.writeFile(
        newWorkbook,
        `DG-商品分析_${getBeginDate("YYYYMMDD")}_${getEndDate(
          "YYYYMMDD"
        )}_数据更新日期${getEndDate()}.xlsx`
      )
    } catch (e) {
      updateMessageList(`导出数据错误:${e}`)
    } finally {
      setDisExportBtn(false)
      setExporting(false)
    }
  }

  // 使用店铺信息接口，获取所有店铺列表
  const getAllShopList = async () => {
    updateMessageList("下载合作商家数据中")
    // 店铺数据下载处理
    // 每次下载个数
    let shopPageSize = 100
    // 下载页码
    let shopPageNo = 1
    // 店铺总数 初始化最大数
    let shopTotal = Infinity
    // 店铺列表
    const shopList = []
    // 循环下载商户信息
    while (shopList.length < shopTotal) {
      const shopResult = await handleGetShopList(shopPageNo, shopPageSize)
      //push店铺信息到shopList
      shopList.push(...shopResult.shop_list)
      // 更新总数？当初始的shopTotal不是最终总数的时候，需要重新计算
      if (shopTotal > shopResult.total) {
        shopTotal = shopResult.total
      }
      updateMessageList(
        `已下载合作商家信息 ${shopList.length} / ${shopTotal}...`
      )
      shopPageNo += 1
    }
    updateMessageList(`合作商家信息下载完成，共 ${shopList.length} 家商家`)
    return shopList
  }

  // 循环获取店铺所有商品, 接收店铺id参数
  const getAllProductList = async (shopId: number, shopName: string) => {
    updateMessageList(`开始下载【${shopName}】商户商品...`)
    // 循环获取所有商品
    // 每次下载个数
    let productPageSize = 1000
    // 下载页码
    let productPageNo = 1
    // 商品总数 初始化最大数
    let productTotal = Infinity
    // 商品列表
    const productList = []
    // 循环下载商户信息
    while (productList.length < productTotal) {
      const productResult = await handleGetProductList(
        shopId,
        productPageNo,
        productPageSize
      )
      //push商品信息到productList
      productList.push(...productResult.product_list)
      // 更新总数？当初始的productTotal不是最终总数的时候，需要重新计算
      if (productTotal > productResult.total) {
        productTotal = productResult.total
      }
      updateMessageList(
        `已下载商品信息 ${productList.length} / ${productTotal}}...`
      )
      productPageNo += 1
    }
    updateMessageList(
      `【${shopName}】商家商品下载完成，共 ${productList.length} 个商品`
    )
    return productList
  }

  // 处理数据采集
  const handleCaptureData = async () => {
    // 禁用导出按钮
    setDisExportBtn(true)
    // 初始化信息
    updateMessageList("", true)
    try {
      // 显示信息框
      handleShowMessageBox()
      // 店铺信息, 初始化为店铺缓存信息
      let shopInfo = getShopInfoFromCache()
      if (!shopInfo) {
        shopInfo = {}
        // 添加信息
        updateMessageList(
          `开始采集 [${requestParams["begin_date"]} 至 ${requestParams["end_date"]}] 合作商家商品数据...`
        )
        // 获取店铺列表
        const shopList = await getAllShopList()
        // 循环获取店铺商品信息
        for (let i = 0; i < shopList.length; i++) {
          const shop = shopList[i]
          const product_list = await getAllProductList(shop.id, shop.name)
          shopInfo[shop.id] = {
            name: shop.name,
            products: product_list
          }
        }

        // 写入店铺缓存
        addShopInfoToCache(shopInfo)
        updateMessageList(`合作商家商品信息已下载完成...`)
      } else {
        // 添加信息
        updateMessageList(
          `[${requestParams["begin_date"]} 至 ${requestParams["end_date"]}]店铺信息已缓存,无需下载...`
        )
      }
    } catch (e) {
      updateMessageList(`出现错误:${e}`)
    } finally {
      setDisExportBtn(false)
    }
  }

  return (
    <ThemeProvider>
      <StyleProvider container={document.getElementById(HOST_ID).shadowRoot}>
        <div className={"dy-talent-tools-btn"}>
          {userLogin ? (
            <Button
              type={"primary"}
              size={"middle"}
              icon={<DownloadOutlined />}
              onClick={handleCaptureData}>
              DG采集
            </Button>
          ) : null}
        </div>
        <DyCompassMessageModal
          show={showMessageBox}
          handleClose={handleCloseMessageBox}
          messages={messageList}
          disBtn={disExportBtn}
          btnLoading={exporting}
          handleExport={handleDownloadDetail}
        />
      </StyleProvider>
    </ThemeProvider>
  )
}

export default DyCompassTool
